#include "FLOW_core/flow_core_pch.h"
#include "FLOW_fsm/FSMTest.h"
#include "LogMgrTest.h"
#include "StrIdMgrTest.h"


#include <iostream>
#include <cctype>

using namespace CORE;
using namespace std;

//#define ENABLE_FSM_TEST 
#define ENABLE_LOG_MGR_TEST
#define ENABLE_STRID_MGR_TEST

class A
{
	DECLARE_RTTI_ROOT_CLASS( A );
};

DEFINE_RTTI_ROOT_CLASS( A );

class C : public A
{
	DECLARE_RTTI_CLASS( C, A );
};

DEFINE_RTTI_CLASS( C, A );

class B : public C
{
	DECLARE_RTTI_CLASS( B, C );
};

DEFINE_RTTI_CLASS( B, C );

class D
{
	DECLARE_RTTI_ROOT_CLASS( D );
};

DEFINE_RTTI_ROOT_CLASS( D );

class MyRefCounted : public CRefCounted
{
};

class MySafeRefCounted : public CSafeRefCounted< SafePtr< MySafeRefCounted > >
{
};

class MySingleton : public Singleton< MySingleton >
{
public:
	MySingleton( ) {}
	~MySingleton( ) {}
	void Hello( )
	{
		cout << "Hello!!!" << endl; 
	}
};

typedef SmartPtr< MyRefCounted > RefPtr;
typedef SafePtr< MySafeRefCounted > SafeRefPtr;

int_t free_function( void )
{
	cout << "Free function!!" << endl;
	return 1;
}

int_t free_function1( int_t a1 )
{
	cout << "Free function!! " << a1 << endl;
	return a1;
}

class ToBeDelegated
{
public:
	int_t member_function( void )
	{
		cout << "Member function!!" << endl;
		return 2;
	}

	int_t member_function1( int_t a1 )
	{
		cout << "Member function!!" << a1 << endl;
		return a1;
	}
};

class ToBeDelegatedDerived : public ToBeDelegated
{
public:
	int_t derived_member_function( void )
	{
		cout << "Derived member function!!" << endl;
		return 4;
	}

	int_t derived_member_function1( int_t a1 )
	{
		cout << "Derived member function!!" << a1 << endl;
		return a1;
	}
};

class PureVirtualBase
{
public:
	virtual int_t virtual_member_function( void ) = 0;

	virtual int_t virtual_member_function1( int_t a1 ) = 0;
};

class Virtual
{
public:
	virtual int_t virtual_member_function( void )
	{
		cout << "Virtual member function!!" << endl;
		return 3;
	}

	virtual int_t virtual_member_function1( int_t a1 )
	{
		cout << "Virtual member function!!" << a1 << endl;
		return a1;
	}
};

class LaHostia : public ToBeDelegatedDerived, public Virtual
{
public:
	virtual int_t multiple_member_function( void )
	{
		cout << "Multiple inheritance member function!!" << endl;
		return 5;
	}

	virtual int_t multiple_member_function1( int_t a1 )
	{
		cout << "Multiple inheritance member function!!" << a1 << endl;
		return a1;
	}
};

template < typename T, typename U = NullType >
struct TestTemplate
{
	TestTemplate( )
	{
		cout << "No specialization!!" << endl;
	}
};

template< typename T >
struct TestTemplate< T, NullType >
{
	TestTemplate( )
	{
		cout << "Partial specialization!!" << endl;
	}
};


int_t main( int_t argc, char_t** argv )
{
#ifdef ENABLE_LOG_MGR_TEST
	CLogMgrTest log_mgr_test;
	log_mgr_test.Test( );
#endif
#ifdef ENABLE_STRID_MGR_TEST
	CStrIdMgrTest strid_mgr_test;
	strid_mgr_test.Test( );
#endif
#ifdef ENABLE_FSM_TEST

	CFSMTest fsmTest;
	fsmTest.Execute();

#else
	char_t ch = (char_t)tolower( 'R' );
	CHECK_CORE_TYPES( );

	RefPtr ref_ptr = new MyRefCounted( );
	RefPtr ref_ptr2 = ref_ptr;
	RefPtr ref_ptr3 = ref_ptr.GetPtr( );

	MySafeRefCounted* p_safe_ref_counted = new MySafeRefCounted( );
	SafeRefPtr safe_ptr = p_safe_ref_counted;
	SafeRefPtr safe_ptr2 = safe_ptr;
	SafeRefPtr safe_ptr3 = safe_ptr.GetPtr( );

	SAFE_DELETE( p_safe_ref_counted );
	
	CVector<int_t> v;
	int_t integer( 5 ); 
	v.push_back( integer );

	B* p_b = NULL;
	B b;
	A* p_a = &b;
	p_b = p_a->DynamicCast< B >( );
	D* p_d = p_a->DynamicCast< D >( );

	Delegate< int_t > dlgt;
	Delegate< int_t, int_t > dlgt1;
	Event< int_t > evt;
	Event< int_t, int_t > evt1;

	dlgt.Set( &free_function );
	int_t result = dlgt( );

	Virtual virtual_obj;
	Virtual* p_virtual = &virtual_obj;
	dlgt.Set( p_virtual, &Virtual::virtual_member_function );
	result = dlgt( );

	ToBeDelegatedDerived derived_obj;
	ToBeDelegatedDerived* p_derived_obj = &derived_obj;
	dlgt.Set( p_derived_obj, &ToBeDelegatedDerived::derived_member_function );
	result = dlgt( );

	dlgt.Set( p_derived_obj, &ToBeDelegated::member_function );
	result = dlgt( );

	LaHostia multiple_inherited_obj;
	LaHostia* p_m_inh_obj = &multiple_inherited_obj;
	dlgt.Set( p_m_inh_obj, &LaHostia::multiple_member_function );
	result = dlgt( );

	dlgt1.Set( &free_function1 );
	result = dlgt1( 1 );

	dlgt1.Set( p_virtual, &Virtual::virtual_member_function1 );
	result = dlgt1( 2 );

	dlgt1.Set( p_derived_obj, &ToBeDelegatedDerived::derived_member_function1 );
	result = dlgt1( 3 );

	dlgt1.Set( p_derived_obj, &ToBeDelegated::member_function1 );
	result = dlgt1( 4 );

	dlgt1.Set( p_m_inh_obj, &LaHostia::multiple_member_function1 );
	result = dlgt1( 5 );

	TestTemplate< int_t > test1;
	TestTemplate< int_t, float_t > test2;

	cout << "Registering delegate was: " << ( evt += dlgt ) << endl;
	cout << "Registering delegate was: " << evt.Register( p_derived_obj, &ToBeDelegated::member_function, 123 ) << endl;
	cout << "Registering delegate was: " << evt.Register( p_derived_obj, &ToBeDelegatedDerived::derived_member_function, 56 ) << endl;
	cout << "Registering delegate was: " << evt.Register( p_virtual, &Virtual::virtual_member_function, 32 ) << endl;
	cout << "Registering delegate was: " << evt.Register( p_m_inh_obj, &LaHostia::multiple_member_function, 16 ) << endl;
	cout << "Registering delegate was: " << evt.Register( &free_function, 0 ) << endl;

	result = evt( );

	//MySingleton* p_singleton = new MySingleton( );
	//delete p_singleton;
	//MySingleton::GetInstance( ).Hello( );

#endif

	return 0;
}

